package cn.fintecher.pangolin.service.dataimp.task;

import cn.fintecher.pangolin.common.enums.*;
import cn.fintecher.pangolin.common.model.UserModel;
import cn.fintecher.pangolin.common.utils.ZWDateUtil;
import cn.fintecher.pangolin.entity.elastic.BaseCase;
import cn.fintecher.pangolin.entity.elastic.PaymentRecord;
import cn.fintecher.pangolin.entity.elastic.PaymentRecordModel;
import cn.fintecher.pangolin.entity.mysql.AssistCase;
import cn.fintecher.pangolin.entity.mysql.CaseInfo;
import cn.fintecher.pangolin.entity.mysql.QAssistCase;
import cn.fintecher.pangolin.entity.mysql.QCaseInfo;
import cn.fintecher.pangolin.service.dataimp.elastic.BaseCaseElastic;
import cn.fintecher.pangolin.service.dataimp.elastic.PaymentRecordElastic;
import cn.fintecher.pangolin.service.dataimp.model.BillModel;
import cn.fintecher.pangolin.service.dataimp.model.CancelBillModel;
import cn.fintecher.pangolin.service.dataimp.repository.AssistCaseRepository;
import cn.fintecher.pangolin.service.dataimp.repository.CaseInfoRepository;
import cn.fintecher.pangolin.service.dataimp.repository.ProcessApplicationRepository;
import org.apache.commons.collections4.IterableUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * @Auther: xiaqun
 * @Description:
 * @Date: 10:54 2019/11/15
 */

@Service("cancelBillFuture")
public class CancelBillFuture {
    @Autowired
    private BaseCaseElastic baseCaseElastic;

    @Autowired
    private CaseInfoRepository caseInfoRepository;

    @Autowired
    private PaymentRecordElastic paymentRecordElastic;

    @Autowired
    private ProcessApplicationRepository processApplicationRepository;

    @Autowired
    private AssistCaseRepository assistCaseRepository;

    /**
     * 处理撤销对账
     */
    @Async
    public CompletableFuture<Map<String, CancelBillModel>> processBill(List<PaymentRecordModel> list) {
        Set<String> caseNumbers = new HashSet<>();
        for (PaymentRecordModel paymentRecordModel : list) {
            caseNumbers.add(paymentRecordModel.getCaseNumber());
        }
        BoolQueryBuilder builder = new BoolQueryBuilder();
        builder.must(QueryBuilders.termsQuery("caseNumber.keyword", caseNumbers));
        Iterable<BaseCase> baseCaseIterable = baseCaseElastic.search(builder);
        Iterable<CaseInfo> caseInfoIterable = caseInfoRepository.findAll(QCaseInfo.caseInfo.caseNumber.in(caseNumbers));
        Iterable<AssistCase> assistCaseIterable = assistCaseRepository.findAll(QAssistCase.assistCase.caseNumber.in(caseNumbers)
                .and(QAssistCase.assistCase.assistStatus.in(AssistStatus.ASSIST_WAIT_ASSIGN, AssistStatus.ASSIST_COLLECTING)));
        List<BaseCase> baseCases = IterableUtils.toList(baseCaseIterable);
        List<CaseInfo> caseInfos = IterableUtils.toList(caseInfoIterable);
        List<AssistCase> assistCases = IterableUtils.toList(assistCaseIterable);
        List<String> ids = new ArrayList<>();
        for (PaymentRecordModel paymentRecordModel : list) {
            ids.add(paymentRecordModel.getId());
        }
        BoolQueryBuilder builder1 = new BoolQueryBuilder();
        builder1.must(QueryBuilders.termsQuery("id.keyword", ids));
        Iterable<PaymentRecord> iterable = paymentRecordElastic.search(builder1);
        List<PaymentRecord> recordList = IterableUtils.toList(iterable);
        Map<String, CancelBillModel> map = new HashMap<>();
        for (BaseCase baseCase : baseCases) {
            CancelBillModel cancelBillModel = new CancelBillModel();
            cancelBillModel.setBaseCase(baseCase);
            List<PaymentRecordModel> paymentRecordModels = cancelBillModel.getPaymentRecordModels();
            List<PaymentRecord> paymentRecords = cancelBillModel.getPaymentRecords();
            for (PaymentRecordModel paymentRecordModel : list) {
                if (baseCase.getCaseNumber().equals(paymentRecordModel.getCaseNumber())) {
                    paymentRecordModels.add(paymentRecordModel);
                }
            }
            for (PaymentRecord paymentRecord : recordList) {
                if (baseCase.getCaseNumber().equals(paymentRecord.getCaseNumber())) {
                    paymentRecords.add(paymentRecord);
                }
            }
            for (CaseInfo caseInfo : caseInfos) {
                if (baseCase.getId().equals(caseInfo.getId())) {
                    cancelBillModel.setCaseInfo(caseInfo);
                    break;
                }
            }
            List<AssistCase> assistCases1 = new ArrayList<>();
            for (AssistCase assistCase : assistCases) {
                if (baseCase.getCaseNumber().equals(assistCase.getCaseNumber())) {
                    assistCases1.add(assistCase);
                }
            }
            cancelBillModel.setAssistCases(assistCases1);
            map.put(baseCase.getCaseNumber(), cancelBillModel);
        }
        return CompletableFuture.completedFuture(map);
    }

    /**
     * 处理状态
     */
    @Async
    public CompletableFuture<BillModel> processStatus(Map.Entry<String, CancelBillModel> entry, UserModel userModel) {
        CancelBillModel cancelBillModel = entry.getValue();
        BaseCase baseCase = cancelBillModel.getBaseCase();
        CaseInfo caseInfo = cancelBillModel.getCaseInfo();
        List<AssistCase> assistCases = cancelBillModel.getAssistCases();
        List<PaymentRecord> paymentRecords = cancelBillModel.getPaymentRecords();
        List<PaymentRecordModel> paymentRecordModels = cancelBillModel.getPaymentRecordModels();
        BillModel model = new BillModel();
        List<PaymentRecord> paymentRecordList = new ArrayList<>();
        List<PaymentRecordModel> paymentRecordModelList = new ArrayList<>();
        double amt = 0d;
        for (PaymentRecordModel paymentRecordModel : paymentRecordModels) {
            paymentRecordModel.setFlag(1);
            amt += paymentRecordModel.getPaymentAmt();
            paymentRecordModelList.add(paymentRecordModel);
        }
        for (PaymentRecord paymentRecord : paymentRecords) {
            paymentRecord.setFlag(1);
            paymentRecordList.add(paymentRecord);
        }
        model.setPaymentRecords(paymentRecordList);
        model.setPaymentRecordModels(paymentRecordModelList);
        baseCase.setLeftAmt(baseCase.getLeftAmt() + amt);
        if (Objects.nonNull(caseInfo)) {
            caseInfo.setLeftAmt(caseInfo.getLeftAmt() + amt);
            caseInfo.setOperator(userModel.getId());
            caseInfo.setOperatorTime(ZWDateUtil.getNowDateTime());
        }
        //判断状态
        List<String> ids = new ArrayList<>();
        for (PaymentRecordModel paymentRecordModel : paymentRecordModels) {
            ids.add(paymentRecordModel.getId());
        }
        BoolQueryBuilder builder = new BoolQueryBuilder();
        builder.must(QueryBuilders.matchPhraseQuery("caseId.keyword", baseCase.getId())).mustNot(QueryBuilders.termsQuery("id.keyword", ids)).must(QueryBuilders.matchPhraseQuery("flag", 0));
        Iterable<PaymentRecord> iterable1 = paymentRecordElastic.search(builder);
        if (iterable1.iterator().hasNext()) {
            List<PaymentRecord> list1 = IterableUtils.toList(iterable1);
            list1.sort((e1, e2) -> e2.getPaymentDate().compareTo(e1.getPaymentDate()));
            baseCase.setLatestPayAmt(list1.get(0).getPaymentAmt());
            baseCase.setLatestPayDate(list1.get(0).getPaymentDate());
            if (baseCase.getLeftAmt() <= 0d) {
                baseCase.setPayStatus(PayStatus.SETTLT);
                baseCase.setClearDate(ZWDateUtil.getNowDate());
                baseCase.setIsClear(BaseSelect.YES);
            } else {
                baseCase.setPayStatus(PayStatus.PARTIAL_PAY);
                baseCase.setClearDate(null);
                baseCase.setIsClear(BaseSelect.NO);
            }
            if (Objects.nonNull(caseInfo)) {
                caseInfo.setLatestPayAmt(list1.get(0).getPaymentAmt());
                caseInfo.setLatestPayDate(list1.get(0).getPaymentDate());
                if (caseInfo.getLeftAmt() <= 0d) {
                    boolean b = processApplicationRepository.existsByCaseIdAndApprovalStageAndFlowType(baseCase.getId(), ApprovalStage.APPROVED_PASS, FlowType.DERATE_APPLY);
                    if (b) {
                        caseInfo.setCaseDataStatus(CaseDataStatus.REDUCE);
                    } else {
                        caseInfo.setCaseDataStatus(CaseDataStatus.SETTLT);
                    }
                    caseInfo.setClearDate(ZWDateUtil.getNowDate());
                    caseInfo.setPayStatus(PayStatus.SETTLT);
                } else {
                    caseInfo.setPayStatus(PayStatus.PARTIAL_PAY);
                    caseInfo.setCaseDataStatus(caseInfo.getCaseStatus());
                    caseInfo.setCaseStatus(null);
                    caseInfo.setClearDate(null);
                }
                model.setCaseInfo(caseInfo);
            }
        } else {
            baseCase.setLatestPayAmt(0d);
            baseCase.setLatestPayDate(null);
            baseCase.setPayStatus(PayStatus.UN_PAY);
            baseCase.setIsClear(BaseSelect.NO);
            if (Objects.nonNull(caseInfo)) {
                caseInfo.setLatestPayAmt(0d);
                caseInfo.setLatestPayDate(null);
                caseInfo.setPayStatus(PayStatus.UN_PAY);
                caseInfo.setCaseDataStatus(caseInfo.getCaseStatus());
                model.setCaseInfo(caseInfo);
            }
        }
        for (AssistCase assistCase : assistCases) {
            if (baseCase.getLeftAmt() > 0) {
                assistCase.setLeftAmt(baseCase.getLeftAmt());
                assistCase.setLatestPayAmt(baseCase.getLatestPayAmt());
                assistCase.setLatestPayDate(baseCase.getLatestPayDate());
                assistCase.setOperatorTime(ZWDateUtil.getNowDateTime());
            }
        }
        model.setAssistCases(assistCases);
        model.setBaseCase(baseCase);
        return CompletableFuture.completedFuture(model);
    }
}
